home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DDJMAG / DDJ9203.ZIP / DRVMONIT.ZIP / LOGCMD.ASM < prev    next >
Assembly Source File  |  1991-11-29  |  50KB  |  1,291 lines

  1. ;---------------------------------------------------------------    
  2. ;logcmd - command processing for device driver monitor         |
  3. ;--------------------------------------------------------------|
  4. ;Copyright 1990, 1992 ASMicro Co.                              |
  5. ;--------------------------------------------------------------|
  6. ;                                                              |
  7. ; 4/15/90                      Rick Knoblaugh                  |
  8. ;--------------------------------------------------------------|
  9. ;include files                                                 |
  10. ;---------------------------------------------------------------    
  11.                 include logequ.inc
  12.                 include logstruc.inc
  13.  
  14. code            segment public  'CODE'
  15.                 assume cs:code, ds:code, es:code
  16. ;--------------------------------------------------------------
  17. ;PUBLIC                                                       |
  18. ;--------------------------------------------------------------
  19.                 public  monitor_process        
  20.                 public  drv_open
  21.                 public  drv_close
  22.                 public  drv_ioctl_in 
  23.                 public  drv_ioctl_out
  24.                 public  drv_non_supt
  25.                 public  patch_flag
  26.                 public  old_user_int
  27.                 public  drv_state
  28.                 public  save_patch
  29.                 public  get_key
  30.                 public  req_header
  31.                 public  show_buffer
  32.                 public  record_cmd
  33.                 public  find_func
  34.                 public  find_sub_func
  35.                 public  config_dat 
  36.                 public  cmd_table 
  37.                 public  old_stack_ptr   
  38.                 public  old_stack_seg  
  39.                 public  logr_stack
  40.                 public  logr_sp   
  41.                 public  prt_to_mem 
  42. ;--------------------------------------------------------------
  43.                         include logdat.inc      ;data for driver monitor
  44.  
  45. ;--------------------------------------------------------------
  46. ;The following perform processing depending on what call into 
  47. ;monitored device driver is occurring.
  48. ;--------------------------------------------------------------
  49. state_handlers  dw      process_nothing
  50.                 dw      process_strat
  51.                 dw      process_int
  52.                 dw      process_ret
  53.  
  54.  
  55. out_table       dw      prt_to_null
  56.                 dw      prt_to_printer
  57.                 dw      prt_to_screen 
  58.                 dw      prt_to_mem   
  59.  
  60.  
  61.  
  62. drv_non_supt    proc    near
  63.                 mov     ax, ERR_UNKNOWN
  64.                 ret
  65. drv_non_supt    endp
  66.  
  67. drv_open        proc    near
  68. drv_close       proc    near
  69.                 mov     ax, OK_STATUS
  70.                 ret
  71. drv_close       endp        
  72. drv_open        endp        
  73.  
  74. ;--------------------------------------------------------------
  75. ;drv_ioctl_out - receive from caller a far ptr to a user      |
  76. ;                buffer area in which to log data, and a dword|
  77. ;                value containing the size in bytes of this   |
  78. ;                data area.                                   |
  79. ;--------------------------------------------------------------
  80. drv_ioctl_out   proc    near
  81.                 les     di, req_header          ;get ptr to request header
  82.                 mov     ax, ERR_GENFAIL         ;default to error
  83. ;is this the number of bytes we are expecting?
  84.                 cmp     es:[di].ioctl_count, size ioctl_out_data
  85.                 jne     short drv_ioctl_o999    ;if not, error
  86. drv_ioctl_o100:
  87.  
  88.                 les     di, es:[di].ioctl_buf_ptr       ;get ptr to DTA
  89.                 push    ds
  90.                 lds     bx, es:[di].user_buf_ptr        ;get user's buffer ptr
  91.                 mov     cs:user_data_ptr.d_offset, bx   ;save it
  92.                 mov     cs:user_data_ptr.d_segment, ds
  93.  
  94.                 lds     bx, es:[di].user_buf_size       ;get size of buffer
  95.                 mov     cs:user_data_size.d_offset, bx  ;save it
  96.                 mov     cs:user_data_size.d_segment, ds
  97.  
  98.                 pop     ds
  99.  
  100.                 mov     ax, OK_STATUS
  101. drv_ioctl_o999:
  102.                 ret
  103. drv_ioctl_out   endp        
  104.  
  105. ;--------------------------------------------------------------
  106. ;drv_ioctl_in - pass back to caller, a far ptr to our count of|
  107. ;               bytes written to user data area, offset of    |
  108. ;               our configuration info, and offset of our     |
  109. ;               command table info.                           |
  110. ;                                                             |
  111. ;--------------------------------------------------------------
  112. drv_ioctl_in    proc    near
  113.                 les     di, req_header            ;get ptr to request header
  114.                 mov     es:[di].ioctl_count, size ioctl_in_data  ;pass count
  115.                 les     di, es:[di].ioctl_buf_ptr ;get ptr to DTA
  116.  
  117.                 mov     ax, offset wrk_data_count ;pass back pointer to
  118.                                                   ;our buffer count      
  119.                 mov     es:[di].drv_buf_count.d_offset, ax  
  120.                 mov     es:[di].drv_buf_count.d_segment, cs
  121.                 
  122.                 mov     ax, offset config_dat
  123.                 mov     es:[di].drv_config_dat, ax
  124.                 mov     ax, offset cmd_table
  125.                 mov     es:[di].drv_cmd_tbl, ax
  126.  
  127.                 mov     ax, OK_STATUS
  128.                 ret
  129.  
  130. drv_ioctl_in    endp        
  131.  
  132. ;--------------------------------------------------------------
  133. ;monitor_process                                              |
  134. ;--------------------------------------------------------------
  135. monitor_process proc    far 
  136.                 cli
  137.                 mov     cs:old_stack_ptr, sp
  138.                 mov     cs:old_stack_seg, ss
  139.                 mov     sp, cs
  140.                 mov     ss, sp
  141.                 mov     sp, offset cs:logr_sp  
  142.                 sti
  143.  
  144.                 cld
  145.                 push    ds
  146.                 push    es
  147.                 push    ax
  148.                 push    bx
  149.                 push    cx
  150.                 push    dx
  151.                 push    di
  152.                 push    si
  153.  
  154.                 push    cs                      ;get our ds
  155.                 pop     ds
  156.  
  157.                 mov     di, drv_state 
  158.                 shl     di, 1
  159. ;
  160. ;Proccess based on which area of driver being monitored generated the
  161. ;user software interrupt.
  162. ;
  163.                 call    word ptr [di + state_handlers]
  164.  
  165.  
  166.                 pop     si
  167.                 pop     di
  168.                 pop     dx
  169.                 pop     cx
  170.                 pop     bx
  171.                 pop     ax
  172.                 pop     es
  173.                 pop     ds
  174.  
  175.                 cli
  176.                 mov     sp, cs:old_stack_ptr
  177.                 mov     ss, cs:old_stack_seg
  178.                 sti
  179.                 iret
  180. monitor_process endp        
  181.  
  182.  
  183. process_nothing proc    near
  184.                 ret
  185. process_nothing endp
  186.  
  187.  
  188.  
  189. ;--------------------------------------------------------------
  190. ;process_strat - store the es:bx ptr to the request header    |
  191. ;                coming into the driver being monitored.  Also|
  192. ;                patch in an int instruction at start of      |
  193. ;                driver's interrupt routine.  Set next state  |
  194. ;                to indicate next int should come from driver |
  195. ;                interrupt routine.                           |
  196. ;--------------------------------------------------------------
  197. process_strat   proc    near
  198.                 mov     mdrv_req_ptr.d_offset, bx      ;save ptr to req header
  199.                 mov     mdrv_req_ptr.d_segment, es
  200.  
  201.                 les     bx, dword ptr old_stack_ptr
  202.                 les     di, dword ptr es:[bx].mdrv_off ;ptr to start of code        
  203.                 mov     mdrv_strat_ptr.d_segment, es
  204. ;
  205. ;Determine if the int instruction that gave us control was patched into
  206. ;the driver being monitored or is part of the driver source code.  This
  207. ;is to decide where to return: at the instruction (replaced with former
  208. ;object code), or after the int instruction.
  209. ;
  210.                 cmp     patch_flag, TRUE        ;indicates that user patched
  211.                 jne     process_s100
  212.                 sub     di, 2                   ;offset of int instruction
  213. ;
  214. ;When return occurs, control will pass back to code at int instruction 
  215. ;which will be overlaid with the original code contents.  Adjust the
  216. ;value on the stack.
  217.                 push    ds
  218.                 lds     bx, dword ptr old_stack_ptr ;get old ss and sp
  219.                 mov     [bx].mdrv_off, di       
  220.                 pop     ds
  221.  
  222.                 mov     ax, save_patch      ;get the original 2 bytes of code
  223.                 mov     es:[di], ax         ;put it back
  224.  
  225.  
  226. process_s100:
  227.                 mov     mdrv_strat_ptr.d_offset, di
  228.  
  229. ;
  230. ;Determine if address of interrupt routine for driver being monitored has
  231. ;been stored yet.  If not, retrieve the address from the device driver
  232. ;header.
  233.  
  234.                 cmp     mdrv_int_ptr.d_segment, NULL   
  235.                 jne     process_s200
  236.                 mov     mdrv_int_ptr.d_segment, es      ;seg of int routine
  237.                 xor     bx, bx                          ;offset header
  238.                 mov     ax, es:[bx].dev_int             
  239.                 mov     mdrv_int_ptr.d_offset, ax       ;offset of int routine
  240. process_s200:
  241.                 mov     di, mdrv_int_ptr.d_offset
  242. ;
  243. ;Save first 2 bytes of code at the interrupt routine.  Patch in the
  244. ;int instruction which will give us control.
  245.  
  246.                 call    save_n_patch         
  247.                 mov     drv_state, EXPECT_INT 
  248.   
  249.                 cmp     header_flag, TRUE       ;printed log header already?
  250.                 je      process_s300
  251.                 call    prt_log_hdr             ;print name, load address etc.
  252.  
  253.                 mov     header_flag, TRUE
  254. process_s300:
  255.                 ret
  256. process_strat   endp
  257.  
  258.  
  259.  
  260. ;--------------------------------------------------------------
  261. ;process_int                                                  |
  262. ;--------------------------------------------------------------
  263. process_int     proc    near
  264. ;
  265. ;First, try to do a little checking to see if this is really the int routine.
  266. ;It's possible that the user of this program did not place the int which 
  267. ;gives us control in the strategy routine.  If things don't look like they
  268. ;should, simply return without attempting any monitoring.
  269. ;
  270.                 les     bx, dword ptr old_stack_ptr
  271.                 les     di, dword ptr es:[bx].mdrv_off ;&driver's int routine
  272.                 mov     ax, es
  273.                                                 ;is this the segment we
  274.                 cmp     ax, mdrv_int_ptr.d_segment ;are expecting?
  275.                 jne     process_i999 
  276.                 sub     di, 2                   ;back to "int" instruction
  277.                 cmp     di,  mdrv_int_ptr.d_offset
  278.                 jne     process_i999 
  279.  
  280.                 inc     drv_req_num             ;count requests to driver
  281.  
  282. ;Replace the int instruction with original contents
  283. ;
  284.                 call    restor_instruc          
  285.  
  286. ;
  287. ;Fix value for the offset of where to return.  Go back 2 bytes to location
  288. ;of int instruction.  
  289.                 les     bx, dword ptr old_stack_ptr
  290.                 mov     es:[bx].mdrv_off, di    ;put adjusted value back
  291.                 les     di, dword ptr es:[bx].mdrv_ret_off 
  292. ;
  293. ;Save ptr to where driver being monitored will return after its int routine
  294. ;completes.
  295. ;  
  296.                 mov     mdrv_ret_ptr.d_offset, di                   
  297.                 mov     mdrv_ret_ptr.d_segment, es
  298. ;
  299. ;Save code at that location and patch in int instruction
  300. ;
  301.                 call    save_n_patch         
  302.                 mov     drv_state, EXPECT_USE_RET           
  303.                 cmp     config_dat.show_cmd_blk, OUTPUT ;show only on return?
  304.                 je      process_i999
  305.  
  306.                 mov     ax, drv_req_num         ;exceeded number to log?
  307.                 cmp     ax, config_dat.max_to_log
  308.                 ja      process_i999            ;if yes, don't log any more
  309. ;
  310. ;Determine if the number of requests so far has reached the request number
  311. ;where the user wishes to start logging.
  312. ;
  313.                 cmp     ax, config_dat.log_start_num  
  314.                 jb      process_i999
  315.  
  316.                 mov     si, offset entry_text        
  317.                 call    record_cmd              ;go log request header etc.
  318. process_i999:  
  319.                 ret
  320. process_int     endp
  321.  
  322.  
  323. ;--------------------------------------------------------------
  324. ;process_ret                                                  |
  325. ;--------------------------------------------------------------
  326. process_ret     proc    near
  327. ;
  328. ;Compare location from which int was generated with the area we expected
  329. ;to generate it.  If for some reason it isn't correct, simply return.
  330.                 les     bx, dword ptr old_stack_ptr
  331.                 les     di, dword ptr es:[bx].mdrv_off     
  332.                 mov     ax, es
  333.  
  334.                 cmp     ax, mdrv_ret_ptr.d_segment 
  335.                 je      process_r100
  336.                 jmp     process_r999            ;far jump
  337. process_r100:
  338.  
  339.                 sub     di, 2                      ;back to "int" instruction
  340.                 cmp     di,  mdrv_ret_ptr.d_offset ;offset we are expecting?
  341.                 je      process_r120
  342.                 jmp     process_r999 
  343. process_r120:
  344. ;
  345. ;Replace the int instruction with original contents
  346. ;
  347.                 call    restor_instruc          
  348.  
  349. ;Fix value for the offset of where to return back to 2 bytes to location
  350. ;of int instruction.  
  351.                 les     bx, dword ptr old_stack_ptr
  352.                 mov     es:[bx].mdrv_off, di                
  353. ;
  354. ;If user has patched user int into the driver being monitored, repatch that
  355. ;location. 
  356. ;  
  357.                 cmp     patch_flag, TRUE 
  358.                 jne     process_r500
  359.  
  360.                 les     di, dword ptr mdrv_strat_ptr.d_offset       
  361. ;
  362. ;Save code at that location and patch in int instruction.
  363. ;
  364.                 call    save_n_patch         
  365. process_r500:
  366.                 mov     drv_state, EXPECT_STRAT
  367.  
  368. ;Show command block only upon entry into the monitored device driver?
  369.  
  370.                 cmp     config_dat.show_cmd_blk, INPUT 
  371.                 je      process_r900
  372.                 mov     ax, drv_req_num         ;exceeded # commands to log?
  373.                 cmp     ax, config_dat.max_to_log
  374.                 jbe     process_r700
  375.                 jmp     process_r999            ;if yes, don't log any more
  376. process_r700:
  377. ;
  378. ;Determine if the number of requests so far have reached the request number
  379. ;where the user wishes to start logging.
  380. ;
  381.                 cmp     ax, config_dat.log_start_num  
  382.                 jae     process_r800        
  383.                 jmp     process_r999            ;far jump
  384. process_r800:
  385.                 mov     si, offset exit_text    ;"Exit"    
  386.                 call    record_cmd              ;go log request header etc.
  387. process_r900:  
  388.                 les     bx, mdrv_req_ptr        ;get ptr to request header
  389.  
  390.                 cmp     block_dev_flag, TRUE    ;is this a block device?
  391.                 jne     process_r950
  392.  
  393.                 cmp     es:[bx].req_hdr_cmd, CMD_INIT 
  394.                 jne     process_r910
  395.  
  396.                 lds     si, es:[bx].cmd0_bpb_ptr ;get ptr to BPB table
  397.                 mov     si, [si]                 ;move from table to ptr
  398.                 jmp     short process_r930
  399. process_r910:
  400.                 cmp     es:[bx].req_hdr_cmd, CMD_BUILD_BPB         
  401.                 jne     process_r950
  402.                 lds     si, es:[bx].cmd2_bpb_ptr ;get ptr to bpb table
  403. process_r930:
  404.                 mov     ax, [si]                ;get sector size
  405.                 mov     cs:sector_size, ax      ;save it          
  406.  
  407.                 push    cs
  408.                 pop     ds                      ;get local ds   
  409. process_r950:
  410.  
  411.                 cmp     log_it, FALSE           ;if command not to be logged
  412.                 je     process_r999
  413.  
  414.                 push    cs
  415.                 pop     es                      ;es=seg of output buffer
  416.  
  417.  
  418.                 cmp     io_table_ptr, NULL      ;is this an I/O command?
  419.                 je      process_r970
  420.                 call    show_buffer             ;if so, go display data
  421. process_r970:
  422. ;
  423. ;do command completion status stuff
  424.  
  425.                 push    es                      ;save print buffer seg
  426.  
  427.                 les     bx, mdrv_req_ptr        ;ptr to request block
  428.  
  429.                 mov     bx, es:[bx].req_hdr_status ;get cmd status
  430.  
  431.                 pop     es
  432.  
  433.                 push    bx                      ;save cmd status
  434.                 mov     si, offset cmd_com_text ;"Command completion "
  435.                 call    put_til_null
  436.                 test    bx, ERR_BIT             ;error?
  437.                 jnz     process_r980            ;if so, go get error code
  438.                 mov     si, offset success_text            
  439.                 jmp     short process_r990
  440.  
  441. process_r980:
  442.                 and     bx, 00ffh               ;get return code portion only
  443.                 cmp     bl, MAX_ERR             ;out of range of error codes?
  444.                 jbe     process_r985
  445.                 mov     si, offset err_msg16    ;unknown error code message
  446.                 jmp     short process_r990
  447. process_r985:
  448.                 shl     bx, 1
  449.                 mov     si, [bx + err_msg_ptrs]
  450.                 
  451. process_r990:
  452.                 call    put_and_skip            ;print status
  453.                 pop     bx                      ;cmd status
  454.                 test    bx, ERR_BIT             ;error?
  455.                 jz      process_r999            ;if no error, return
  456.  
  457.                 cmp     config_dat.wait_key_err, TRUE ;stop on errors?
  458.                 jne     process_r999
  459.  
  460.                 mov     si, offset stop_msg
  461.                 call    put_and_skip
  462.                 call    get_key
  463.  
  464.  
  465. process_r999:  
  466.                 ret
  467. process_ret     endp
  468.  
  469. ;--------------------------------------------------------------
  470. ;show_buffer - Called just after driver's interrupt routine   |
  471. ;              completes and it has been determined that the  |
  472. ;              command processed was an I/O command.          |
  473. ;                                                             |
  474. ;              Check user configured options for displaying   |
  475. ;              I/O buffers (e.g. show only reads, etc.)       |
  476. ;              If configured to display buffers for this      |
  477. ;              type of command, write the data.               |
  478. ;                                                             |
  479. ;                                                             |
  480. ;              Enter:   ds = our local data                   |
  481. ;                       di = offset into output buffer        |
  482. ;                                                             |
  483. ;               Exit:   di = offset of next output buffer     |
  484. ;                            position.                        |
  485. ;   Save ds register                                          |
  486. ;--------------------------------------------------------------
  487. show_buffer     proc    near
  488.                 push    ds
  489.                 les     bx, mdrv_req_ptr        ;get pointer to cmd
  490.                 cmp     func_req_ptr.d_segment, NULL
  491.                 je      show_b100
  492. ;
  493. ;if command has a function, get ptr to it.
  494. ;
  495.                 les     bx, func_req_ptr         ;get pointer to cmd
  496.  
  497. show_b100:
  498.  
  499. ;See if block size is indicated in the command (with MSCDEX,
  500. ;cooked or raw dictates block size).
  501. ;
  502.                 mov     si, io_table_ptr        ;get ptr to i/o info        
  503.                 cmp     [si].io_bs_indic, TRUE
  504.                 je      show_b200               ;use BPB block size
  505.                                                 ;(1 byte if char)
  506.  
  507.                 add     bx, [si].io_off_indic   ;point to cmd block byte
  508.                                                 ;that tells size                
  509.                 add     si,  size io_table      ;get to optional table elements
  510.                 
  511. show_b150:
  512.                 mov     al, [si].io_bs_value    ;get value that tells blk size
  513.                 cmp     es:[bx], al             ;match with cmd req blk value?
  514.                 je      show_b180
  515.                 cmp     al, TABLE_TERM          ;cmd block not right?
  516.                 jne     show_b170
  517.                 jmp     show_b999               ;far jump to exit                     
  518. show_b170:
  519.                 add     si, size io_bs_elements ;get to next value to match
  520.                 jmp     short show_b150
  521. show_b180:
  522.                 mov     ax, [si].io_bs
  523.                 mov     sector_size, ax
  524.                 mov     bx, mdrv_req_ptr.d_offset ;point back to start cmd blk
  525.                 cmp     func_req_ptr.d_segment, NULL
  526.                 je      show_b190         
  527.                 mov     bx, func_req_ptr.d_offset ;point back to
  528.                                                 ;start of cmd block
  529. show_b190:
  530.                 mov     si, io_table_ptr        ;get ptr to i/o info        
  531. show_b200:
  532.                 push    bx                      ;save start of cmd buffer
  533.                 add     bx, [si].io_count     
  534.                 mov     ax, es:[bx]             ;get count
  535.                 pop     bx
  536.                 mov     sector_count, ax
  537.                 add     bx, [si].io_buf_ptr_off     
  538.  
  539.                 cmp     [si].io_type, INPUT     ;is this input or output?
  540.                 jne     show_b210
  541.  
  542.                 cmp     config_dat.show_buf_in, TRUE ;show input buffers?
  543.                 jne     show_b999
  544.  
  545.                 mov     ax, config_dat.max_show_in ;get max configured to show
  546.                 mov     max_blocks, ax
  547.                 jmp     short show_b230
  548. show_b210:        
  549.                 cmp     config_dat.show_buf_out, TRUE ;show output buffers?
  550.                 jne     show_b999
  551.  
  552.                 mov     ax, config_dat.max_show_out  ;max configured to show 
  553.                 mov     max_blocks, ax
  554. show_b230:
  555.                 mov     block_count, 1          ;start counting the blocks
  556.  
  557.                 push    es                      ;save segment of cmd block
  558.  
  559.                 push    cs
  560.                 pop     es                      ;es=seg of output buffer
  561.         
  562.                 call    skip_line
  563.                 mov     si, offset data_buf_text
  564.                 call    put_and_skip
  565.  
  566.                 pop     es
  567.  
  568.                 lds     si, es:[bx]             ;get ptr to i/o buffer
  569.  
  570.                 push    cs
  571.                 pop     es                      ;get es = local data
  572.  
  573. show_b240:
  574.                 mov     bx, cs:sector_count     ;get number of chars or blocks
  575.                 cmp     cs:sector_size, 1       ;doing characters?
  576.                 je      show_b250
  577. show_b245:
  578.                 mov     ax, cs:max_blocks
  579.                 cmp     cs:block_count, ax      ;showed maximum desired?
  580.                 ja      show_b999
  581.                 call    put_out_block
  582.  
  583.                 mov     bx, cs:sector_size
  584. show_b250:
  585.  
  586.                 call    dump_n_count
  587.  
  588.                 cmp     cs:sector_size, 1       ;doing characters?
  589.                 je      show_b999               ;then done
  590.  
  591.                 call    skip_line
  592.                 dec     cs:sector_count
  593.                 jz      show_b999
  594.                 inc     cs:block_count
  595.                 jmp     short show_b245
  596.  
  597. show_b999:                  
  598.                 pop     ds
  599.                 ret
  600. show_buffer     endp        
  601.  
  602.  
  603. ;--------------------------------------------------------------
  604. ;put_out_block - print "block " and block number.             |
  605. ;                                                             |
  606. ;               Enter:  block_count contains number           |
  607. ;   Save ds, si registers                                     |
  608. ;--------------------------------------------------------------
  609. put_out_block   proc    near
  610.                 push    ds
  611.                 push    si
  612.  
  613.                 push    cs
  614.                 pop     ds              ;get ds=our local data
  615.                 mov     si, offset block_text
  616.                 call    put_til_null
  617.                 mov     ax, block_count
  618.                 call    out_int
  619.                 call    term_line
  620.                 call    out_line
  621.                 call    skip_line
  622.  
  623.                 pop     si
  624.                 pop     ds
  625.                 ret
  626. put_out_block   endp
  627.  
  628.  
  629.  
  630. ;--------------------------------------------------------------
  631. ;restor_instruc - replace the 2 bytes of code where int       |
  632. ;                 instruction had been patched in.            |
  633. ;                                                             |
  634. ;               Enter:  es:di location to be patched          |
  635. ;--------------------------------------------------------------
  636. restor_instruc  proc    near
  637.                 mov     ax, save_code
  638.                 mov     es:[di], ax     ;put it into the code
  639.                 ret
  640. restor_instruc  endp
  641.  
  642. ;--------------------------------------------------------------
  643. ;save_n_patch - Save the 2 bytes of code where int instruction|
  644. ;               is to be placed.  Place int instruction in    |
  645. ;               the code.                                     |
  646. ;                                                             |
  647. ;               Enter:  es:di =  location to be patched       |
  648. ;--------------------------------------------------------------
  649. save_n_patch    proc    near
  650.                 mov     ax, (USER_INT shl 8) or INT_OP_CODE
  651.                 xchg    ax, es:[di]
  652.                 mov     save_code, ax
  653.                 ret
  654. save_n_patch    endp
  655.  
  656. ;--------------------------------------------------------------
  657. ;record_cmd - Make call to do table lookup on command.  Also, |
  658. ;             determine if this type of command is to be      |
  659. ;             logged.  If to be logged, write out the         |
  660. ;             description of the command and dump the cmd     |
  661. ;             request block (and any "packet" area).          |
  662. ;                                                             |
  663. ;             Enter:  ds = our local data                     | 
  664. ;                     si = offset of string indicating if     |
  665. ;                          we are examining the cmd request   |
  666. ;                          on "Entry" to or "Exit" from the   |
  667. ;                          driver's interrupt routine.        |
  668. ;                                                             |
  669. ;              Exit:  di = next offset in output buffer.      |
  670. ;                                                             |
  671. ;    DS register saved.                                       |
  672. ;--------------------------------------------------------------
  673. record_cmd      proc    near
  674.                 les     bx, mdrv_req_ptr        ;ptr to request block
  675.                 push    si                      ;save ptr to "Entry" or "Exit"
  676.                 call    find_func
  677.                 mov     bx, si                  ;save ptr to cmd table
  678.                 pop     si
  679.                 mov     di, offset out_buf
  680.                 cmp     log_it, FALSE           ;don't log this command?
  681.                 je      record_c900
  682.  
  683.                 push    ds
  684.                 pop     es                      ;get es = local ds
  685.  
  686.                 call    skip_line
  687.                 call    put_til_null            ;output "Entry" or "Exit"
  688.                 mov     si, offset driv_req_text
  689.                 call    put_til_null            ;output "Driver request"  
  690.                 mov     ax, drv_req_num
  691.                 call    out_int                 ;output sequence number
  692.                 mov     si, bx                  ;si = ptr to cmd info table
  693.                 call    out_descrip             ;output command description
  694. ;
  695. ;si contains offset of cmd info table entry 
  696. ;
  697.                 call    prt_req                 ;print cmd request block
  698.                 cmp     byte ptr [si].ri_func_ptr, NULL  ;a function?
  699.                 je      record_c900
  700.                 call    skip_line
  701.  
  702.  
  703.                 mov     bx, hold_sub_det_ptr    ;get fuction table offset
  704.                 mov     si, [bx].fd_descrip     ;function description 
  705.                 call    put_and_skip            ;go print it        
  706.  
  707.                 mov     bl, [bx].fd_packet_len  ;length of function packet
  708.                 sub     bh, bh
  709.                 push    ds                              
  710.                 lds     si, func_req_ptr
  711.                 call    dump_n_count 
  712.                 call    skip_line
  713.                 pop     ds
  714.  
  715. record_c900:
  716.                 ret
  717. record_cmd      endp
  718.  
  719. ;--------------------------------------------------------------
  720. ;find_func - Find the command requested in the table of       |
  721. ;            command information.  Also, determine if         |
  722. ;            requested command should be logged.              |
  723. ;                                                             |
  724. ;               Enter: es:bx = ptr to function request        |
  725. ;                                                             |
  726. ;                Exit: si = offset of table entry             |
  727. ;--------------------------------------------------------------
  728.  
  729. find_func       proc    near
  730.                 mov     al, es:[bx].req_hdr_cmd
  731. ;
  732. ;Search through a table of commands.  Since some drivers such as those
  733. ;used with MSCDEX use nonsequential command codes, we can't simply index
  734. ;into the table.
  735. ;
  736.                 mov     si, offset cmd_table
  737. find_func100:
  738.                 cmp     al, [si].ri_cmd_code    ;found?              
  739.                 je      find_func500
  740.                 cmp     byte ptr [si].ri_cmd_code, TABLE_TERM ;not found?
  741.                 je      find_func500
  742.                 add     si, size req_info       ;advance to next entry
  743.                 jmp     short find_func100
  744.  
  745. find_func500:
  746.                 mov     ax, [si].ri_iotbl_ptr
  747.                 mov     io_table_ptr, ax        ;save I/O table information
  748.  
  749.                 mov     ax, NULL
  750.                 mov     func_req_ptr.d_segment, ax ;default to no function
  751.                 mov     func_req_ptr.d_offset, ax  
  752.  
  753.                 cmp     [si].ri_func_ptr, ax   ;is there a function?
  754.                 je      find_func600
  755.                                    
  756.                 push    si
  757.                 mov     si, [si].ri_func_ptr    ;ptr to function table
  758.                 call    find_sub_func           ;return bx = function
  759.                                                 ;detail info table entry
  760.                 pop     si
  761.  
  762. find_func600:
  763.  
  764.                 mov     log_it, TRUE            ;default to logging
  765.                 cmp     config_dat.log_all, TRUE
  766.                 je      find_func900
  767.                 
  768.                 cmp     byte ptr [si].ri_log_flag, FALSE
  769.                 je      find_func800
  770.  
  771.                 cmp     [si].ri_func_ptr, NULL  ;is there a function?
  772.                 je      find_func900
  773.                                         
  774.  
  775.                 cmp     byte ptr [bx].fd_log_flag, TRUE ;log this function?
  776.                 je      find_func900                         
  777. find_func800:
  778.  
  779.                 mov     log_it, FALSE           ;don't log this command
  780. find_func900:
  781.                 ret                
  782. find_func       endp
  783.  
  784.  
  785.  
  786.  
  787. ;--------------------------------------------------------------
  788. ;find_sub_func - find detailed function table entry for       |
  789. ;                command.                                     |
  790. ;                                                             |
  791. ;               Enter: ds:si = ptr to function table          |
  792. ;                      es:bx = ptr to command request block   |
  793. ;                                                             |
  794. ;                Exit:  bx = offset of detailed function      |
  795. ;                            table entry.                     |
  796. ;--------------------------------------------------------------
  797. find_sub_func   proc    near
  798.                 push    di
  799.                 push    es
  800.  
  801.                 push    es
  802.                 push    bx                      ;save ptr to cmd req block
  803.                 
  804.                 add     bx, [si].f_off_ptr  
  805.                 les     bx, es:[bx]             ;get ptr to function
  806.                 
  807.                 mov     func_req_ptr.d_segment, es ;save it
  808.                 mov     func_req_ptr.d_offset, bx
  809.  
  810.                 pop     bx
  811.                 pop     es                      ;restore ptr to cmd req block
  812.  
  813.  
  814.  
  815.                 cmp     byte ptr [si].f_sub_in, TRUE    ;is function code
  816.                                                         ;here or pointed to?
  817.                 je      find_sub_f100
  818.  
  819.                 add     bx, [si].f_off_ptr  
  820.                 les     bx, es:[bx]             ;get ptr to function
  821.                 
  822.  
  823.  
  824. find_sub_f100:
  825. ;
  826. ;es:bx holds ptr to start of command block (or subcommand block).  Determine
  827. ;where major code and minor code (if any) are found within cmd block.
  828. ;
  829.                 mov     di, [si].f_off_cat_code
  830.                 mov     al, es:[bx + di]        ;get major code
  831.                 mov     ah, NULL                ;default to no minor code
  832.                 cmp     [si].f_off_fun_code, NULL  ;no minor code?
  833.                 je      find_sub_f200
  834.  
  835.                 mov     di, [si].f_off_fun_code     
  836.                 mov     ah, es:[bx + di]        ;get minor code
  837.  
  838.  
  839. find_sub_f200:
  840.                 mov     bx, offset [si].f_detail_ptr ;get ptr to detailed info
  841. find_sub_f300:
  842.                 cmp     ax, word ptr [bx].fd_cat_code ;codes found in table?
  843.                 je      find_sub_f600
  844.  
  845. find_sub_f500:
  846.                 cmp     byte ptr [bx].fd_cat_code, TABLE_TERM ;not found?
  847.                 je      find_sub_f600
  848.                 add     bx, size func_detail    ;advance to next entry
  849.                 jmp     short find_sub_f300
  850. find_sub_f600:
  851.                 mov     ax, [bx].fd_iotbl_ptr
  852.                 mov     io_table_ptr, ax        ;save io table information
  853.                 mov     hold_sub_det_ptr, bx
  854.                 pop     es
  855.                 pop     di
  856.  
  857.                 ret
  858. find_sub_func   endp
  859.  
  860.  
  861. ;--------------------------------------------------------------
  862. ; out_int - format a nonzero binary number to ASCII and       |
  863. ;           place formatted number into output buffer.        |
  864. ;                                                             |
  865. ;               Enter: ax = binary number.                    |
  866. ;                   es:di = ptr to output buffer.             |
  867. ;                                                             |
  868. ;                Exit: di = next offset in output buffer.     |
  869. ;--------------------------------------------------------------
  870.  
  871. out_int         proc    near
  872.                 push    bx
  873.                 push    cx
  874.                 push    si
  875.                 add     di, 4
  876.                 mov     si, di                 ;advance to last digit
  877.                 mov     cx, 5                  ;5 digits
  878.                 mov     bx, 10                 ;divide by 10
  879. out_i100:
  880.                 xor     dx, dx
  881.                 div     bx
  882.                 add     dl, '0'                ;make ASCII
  883.                 or      ax, ax
  884.                 jnz     out_i200
  885.                 cmp     dl, '0'
  886.                 jne     out_i200
  887.                 mov     dl, ' '                 ;no leading zeros
  888. out_i200:
  889.                 mov     es:[si], dl             ;get remainder
  890.                 dec     si
  891.                 loop    out_i100
  892.                 add     di, 8                   ;need some space after number
  893.  
  894.                 pop     si
  895.                 pop     cx        
  896.                 pop     bx
  897.                 ret
  898. out_int         endp
  899.  
  900.  
  901.  
  902. out_descrip     proc    near
  903.                 push    si
  904.                 mov     si, [si].ri_descrip     ;get ptr to cmd description
  905.                 call    put_and_skip            ;print it
  906.                 pop     si
  907.                 ret
  908. out_descrip     endp
  909.  
  910.  
  911.  
  912.  
  913.  
  914. get_key         proc    near
  915.                 sub     ah, ah
  916.                 int     16h
  917.                 ret
  918. get_key         endp
  919.  
  920.  
  921.  
  922. ;--------------------------------------------------------------
  923. ;prt_log_hdr - print the device name, type, and load address  |
  924. ;              to the configured output device.               |
  925. ;                                                             |
  926. ;               Enter: es = segment where driver is loaded.   |
  927. ;                      ds = our local data.                   |
  928. ;                                                             |
  929. ;                Exit: di = next offset in output buffer.     |
  930. ;--------------------------------------------------------------
  931. prt_log_hdr     proc    near
  932.                 mov     bx, offset block_text
  933.                 mov     block_dev_flag, TRUE
  934.  
  935.                 push    es
  936.                 pop     ds              ;get ds=monitored driver's segment
  937.  
  938.                 push    cs
  939.                 pop     es              ;get es=local segment
  940.  
  941.                 xor     si, si
  942.                 test    byte ptr [si].dev_attrib.w_msb, 80h   ;char device?
  943.                 jz      prt_log_h200
  944.                 mov     di, offset es:head_drv_name
  945.                 mov     cx, HEAD_DRV_NLEN
  946.  
  947.                 mov     si, size dev_header   ;point to device name
  948.                 rep     movsb                 ;move into buffer
  949.  
  950.                 mov     bx, offset es:char_text
  951.                 mov     es:block_dev_flag, FALSE  ;flag as a char device
  952.  
  953.  
  954. prt_log_h200:
  955.                 mov     si, bx          ;offset of device description
  956.                 push    ds              ;save monitored driver's segment
  957.  
  958.                 push    es
  959.                 pop     ds              ;ds = local data
  960.  
  961.                 mov     di, offset head_dev_type
  962.                 call    put_til_null    ;output heading line         
  963.                 mov     di, offset head_load
  964.  
  965.                 pop     ds              ;restore driver segment
  966.                 xor     si, si
  967.                 call    format_seg
  968.  
  969.                 push    es
  970.                 pop     ds
  971.  
  972.                 mov     di, offset out_buf
  973.                 push    di
  974.                 mov     si, offset head_line 
  975.                 call    put_til_null    ;move heading into buffer
  976.                 call    term_line
  977.                 pop     di
  978.                 call    out_line
  979.                 ret
  980. prt_log_hdr     endp        
  981.  
  982.  
  983. prt_req         proc    near
  984.                 push    ds
  985.                 push    si
  986.                 lds     si, mdrv_req_ptr
  987.                 sub     bh, bh                
  988.                 mov     bl, [si]                ;get number of bytes
  989.                 call    dump_n_count 
  990.                 pop     si
  991.                 pop     ds
  992.                 ret
  993. prt_req         endp
  994.  
  995. ;--------------------------------------------------------------
  996. ;dump_n_count - do a dump of specified area.                  |
  997. ;                                                             |
  998. ;               Enter: ds:si = ptr to area.                   |
  999. ;                         bx = number of bytes.               |
  1000. ;                Exit:    di = start of output buffer         |
  1001. ;--------------------------------------------------------------
  1002. dump_n_count    proc    near
  1003.                 call    dump_a_line
  1004.                 call    out_line     
  1005.                 cmp     bx, 10h
  1006.                 jbe     dump_n_c200
  1007.                 sub     bx, 10h
  1008.                 jmp     short dump_n_count
  1009. dump_n_c200:
  1010.                 ret
  1011. dump_n_count    endp
  1012.  
  1013.  
  1014. ;--------------------------------------------------------------
  1015. ;dump_a_line - given a ptr ds:si to a buffer, form 10h bytes  |
  1016. ;              of dump data at es:di.                         |
  1017. ;--------------------------------------------------------------
  1018.  
  1019. dump_a_line     proc    near
  1020.                 push    di                      ;save start print buf
  1021.                 call    format_seg
  1022.                 add     di,2                    ;leave some space
  1023.                 mov     cx, 10h
  1024.                 push    ds
  1025.                 push    si                      ;save start of data
  1026. dump_a_l100:
  1027.                 lodsb
  1028.                 cmp     si, 0                   ;did offset just wrap?
  1029.                 jne     dump_a_l150
  1030.                 mov     ax, ds                  ;if so, get to new
  1031.                 add     ax, 1000h               ;64k
  1032.                 mov     ds, ax                  
  1033. dump_a_l150:
  1034.                 call    put_hex_dig      
  1035.                 cmp     cl, 9
  1036.                 jne     dump_a_l200
  1037.                 mov     al, '-'
  1038.                 mov     es:[di],al
  1039. dump_a_l200:
  1040.                 inc     di
  1041.                 loop    dump_a_l100
  1042.                 pop     si
  1043.                 pop     ds
  1044.                 add     di, 3
  1045.                 mov     cx, 10h
  1046. dump_a_l250:
  1047.                 lodsb
  1048.                 cmp     si, 0                   ;did offset just wrap?
  1049.                 jne     dump_a_l260
  1050.                 mov     ax, ds                  ;if so, get to new
  1051.                 add     ax, 1000h               ;64k
  1052.                 mov     ds, ax                  
  1053. dump_a_l260:
  1054.                 cmp     al, ' '
  1055.                 jae     dump_a_l300
  1056.                 mov     al, '.'
  1057. dump_a_l300:
  1058.                 stosb
  1059.                 loop    dump_a_l250        
  1060.                 call    term_line 
  1061.                 pop     di
  1062.                 ret
  1063. dump_a_line     endp
  1064.  
  1065. clear_line      proc    near
  1066.                 push    di
  1067.                 mov     cx, 40
  1068.                 mov     ax, '  ' 
  1069.                 rep     stosw
  1070.                 pop     di
  1071.                 ret
  1072. clear_line      endp
  1073.  
  1074. ;--------------------------------------------------------------
  1075. ;format_seg - format segment and offset in ds:si in ASCII     |
  1076. ;             as follows:                                     |
  1077. ;                          xxxx:xxxx                          |
  1078. ;             Put into buffer from ptr es:di                  |
  1079. ;                                                             |
  1080. ;             Exit: di = next offset in output buffer.        |
  1081. ;--------------------------------------------------------------
  1082.  
  1083. format_seg      proc    near
  1084.                 mov     ax, ds                  ;do the segment
  1085.                 mov     cx, 2                   ;2 words
  1086. format_s100:
  1087.                 xchg    al, ah                  ;want to print MSB first
  1088.                 mov     dl, ah                  ;save LSB
  1089.                 call    put_hex_dig
  1090.                 mov     al, dl
  1091.                 call    put_hex_dig
  1092.                 mov     al, ':'
  1093.                 stosb
  1094.                 mov     ax, si                  ;do the offset
  1095.                 loop    format_s100
  1096.                 mov     byte ptr es:[di - 1], ' ' ;ignore last ':'
  1097.                 ret
  1098. format_seg      endp        
  1099.                 
  1100.  
  1101.  
  1102.  
  1103. ;--------------------------------------------------------------
  1104. ;out_line - print line at cs:out_buf.  Reset di to beginning. |
  1105. ;                                                             |
  1106. ;--------------------------------------------------------------
  1107. out_line        proc    proc
  1108.                 push    bx
  1109.                 push    si
  1110.                 push    ds
  1111.  
  1112.                 push    cs
  1113.                 pop     ds                      ;get ds = cs
  1114.                 mov     di, offset out_buf
  1115.                 mov     si, di
  1116.                 mov     bx, config_dat.output_device
  1117.                 shl     bx, 1                   ;get command code
  1118.                 call    word ptr [bx + out_table]
  1119.                 call    clear_line
  1120.  
  1121.                 pop     ds
  1122.                 pop     si
  1123.                 pop     bx
  1124.                 ret
  1125. out_line        endp        
  1126.  
  1127.  
  1128.  
  1129.  
  1130.  
  1131.  
  1132. prt_to_null     proc    near
  1133.                 ret
  1134. prt_to_null     endp        
  1135.  
  1136.  
  1137. prt_to_screen   proc    near
  1138.                 mov     ah, 14                  ;teletype
  1139.                 mov     bl, 0fh                 ;intense white
  1140.                 lodsb
  1141.                 or      al, al                  ;end of data?
  1142.                 jz      ptr_to_sc900
  1143.                 int     10h
  1144.                 jmp     short prt_to_screen  
  1145. ptr_to_sc900:
  1146.                 ret
  1147. prt_to_screen   endp        
  1148.  
  1149. prt_to_printer  proc    near
  1150.                 mov     dx, LPT1
  1151. ptr_to_pr100:
  1152.                 mov     ah, 0                   ;print char
  1153.                 lodsb
  1154.                 or      al, al                  ;end of data?
  1155.                 jz      ptr_to_pr900
  1156.                 int     17h
  1157.                 jmp     short ptr_to_pr100   
  1158. ptr_to_pr900:
  1159.                 ret
  1160. prt_to_printer  endp        
  1161.  
  1162. prt_to_mem      proc    near
  1163.                 push    di                      ;save buffer ptr        
  1164.                 push    es
  1165.                 les     di, user_data_ptr       ;get user's buf ptr
  1166.                 mov     ax, es
  1167.                 cmp     ax, NULL                ;has user made IOCTL yet?
  1168.                 je      prt_to_mi900            ;if not, can't write
  1169.  
  1170.                 les     di, wrk_data_ptr        ;get working ptr
  1171. ;
  1172. ;Has user reset the buffer count?  If so, set work pointer to start of
  1173. ;user buffer.
  1174.  
  1175.                 cmp     wrk_data_count.d_segment, 0 
  1176.                 ja      prt_to_mi100                
  1177.  
  1178.                 cmp     wrk_data_count.d_offset, 0
  1179.                 ja      prt_to_mi100                
  1180.  
  1181.                 les     di, user_data_ptr
  1182.                 mov     wrk_data_ptr.d_offset, di
  1183.                 mov     wrk_data_ptr.d_segment, es
  1184.  
  1185. prt_to_mi100:
  1186.                 mov     dx, user_data_size.d_segment  ;is user buffer full?
  1187.                 cmp     dx, wrk_data_count.d_segment
  1188.                 ja      prt_to_mi120
  1189.  
  1190.                 mov     dx, user_data_size.d_offset 
  1191.                 cmp     dx, wrk_data_count.d_offset
  1192.                 ja      prt_to_mi120
  1193.                 jmp     short prt_to_mi900      ;if so, can't write
  1194. prt_to_mi120:
  1195.                 movsb     
  1196.              
  1197.                 cmp     di, 0                   ;did we just wrap?
  1198.                 jne     prt_to_mi150
  1199.  
  1200.                 mov     ax, es                  ;if so, get to new
  1201.                 add     ax, 1000h               ;64k
  1202.                 mov     es, ax                  
  1203.  
  1204. prt_to_mi150:
  1205.                 inc     wrk_data_count.d_offset
  1206.                 jnz     prt_to_mi200
  1207.                 inc     wrk_data_count.d_segment
  1208.  
  1209. prt_to_mi200:
  1210.                 cmp    byte ptr [si], NULL      ;end of line?
  1211.                 jne    prt_to_mi100             ;if not, continue
  1212.  
  1213.  
  1214. prt_to_mi900:
  1215.  
  1216.                 mov     wrk_data_ptr.d_offset, di       ;save where left off
  1217.                 mov     wrk_data_ptr.d_segment, es
  1218.  
  1219.                 pop     es
  1220.                 pop     di
  1221.                 ret
  1222. prt_to_mem      endp        
  1223.  
  1224. skip_line       proc    near
  1225.                 mov     word ptr cs:[di],  (CR SHL 8) OR LF
  1226.                 add     di, 2
  1227.                 ret
  1228. skip_line       endp
  1229.  
  1230. term_line       proc    near
  1231.                 call    skip_line
  1232.                 mov     byte ptr cs:[di], NULL
  1233.                 inc     di
  1234.                 ret
  1235. term_line       endp
  1236.  
  1237.  
  1238. put_til_null    proc    near
  1239.                 lodsb
  1240.                 or      al, al
  1241.                 jz      put_til_900
  1242.                 stosb
  1243.                 jmp     short put_til_null
  1244. put_til_900:
  1245.                 ret
  1246. put_til_null    endp
  1247.  
  1248. put_and_skip    proc    near
  1249.                 call    put_til_null            ;put it in buffer
  1250.                 call    term_line
  1251.                 call    out_line                ;print it
  1252.                 call    skip_line
  1253.                 ret        
  1254. put_and_skip    endp
  1255.  
  1256. put_hex_dig     proc    near
  1257.                 push    cx
  1258.                 mov     cx, 2                   ;2 digits in al
  1259.                 mov     ah, al
  1260. put_hex_100:
  1261.                 shr     al, 1
  1262.                 shr     al, 1
  1263.                 shr     al, 1
  1264.                 shr     al, 1
  1265.                 cmp     al, 9
  1266.                 ja      put_hex_500
  1267.                 add     al, '0'
  1268.                 jmp     short put_hex_900
  1269. put_hex_500:
  1270.                 add     al, 'A' - 10
  1271. put_hex_900:
  1272.                 stosb
  1273.                 mov     al, ah
  1274.                 shl     al, 1        
  1275.                 shl     al, 1        
  1276.                 shl     al, 1        
  1277.                 shl     al, 1        
  1278.                 loop    put_hex_100
  1279.                 pop     cx
  1280.                 ret
  1281.  
  1282. put_hex_dig     endp
  1283.  
  1284.  
  1285. out_buf         db      256 dup(' ')
  1286. end_out_buf     EQU     $ - out_buf
  1287.  
  1288.  
  1289. code            ends
  1290.                 end
  1291.